﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using umbraco.BasePages;
using umbraco.cms.presentation.Trees;
using umbraco;
using System.Text;

namespace CodeGecko.Umbraco.DataTypes.CustomTreeHandler.Umb40x
{
    public partial class DoctypeTreeInit : UmbracoEnsuredPage
    {
        //protected PlaceHolder PlaceHolderJavascript;

        /// <summary>
        /// If there is not application or tree specified in a query string then this is the application to load.
        /// </summary>
        private const string DEFAULT_APP = "content";

        protected void Page_Load(object sender, EventArgs e)
        {
            TreeService treeSvc = new TreeService();
            treeSvc.App = GetCurrApp();
            treeSvc.ShowContextMenu = TreeRequestParams.Instance.ShowContextMenu;
            treeSvc.IsDialog = TreeRequestParams.Instance.IsDialog;
            treeSvc.DialogMode = TreeRequestParams.Instance.DialogMode;
            treeSvc.TreeType = TreeRequestParams.Instance.TreeType;

            // Validate permissions
            if (!ValidateUserApp(treeSvc.App)) throw new ArgumentException("The current user doesn't have access to this application. Please contact the system administrator.");

            //find all tree definitions that have the current application alias that are ACTIVE
            List<TreeDefinition> activeTreeDefs = TreeDefinitionCollection.Instance.FindActiveTrees(treeSvc.App);
            //find all tree defs that exists for the current application regardless of if they are active
            List<TreeDefinition> appTreeDefs = TreeDefinitionCollection.Instance.FindTrees(treeSvc.App);

            //Create a list of active BaseTree's for this application
            List<BaseTree> activeTrees = new List<BaseTree>();
            //Create a list of ALL BaseTree's for this application
            List<BaseTree> appTrees = new List<BaseTree>();

            //Create the BaseTree's based on the tree definitions found
            foreach (TreeDefinition treeDef in appTreeDefs) {
                //create the tree and initialize it
                BaseTree bTree = treeDef.CreateInstance();
                bTree.SetTreeParameters(TreeRequestParams.Instance);

                //store the created tree
                appTrees.Add(bTree);
                if (treeDef.Tree.Initialize) activeTrees.Add(bTree);
            }

            //Render out the JavaScript associated with all of the trees for the application
            RenderTreeJS(appTrees);

            //if there is only one tree to render, we don't want to have a node to hold sub trees, we just want the
            //stand alone tree, so we'll just add a TreeType to the TreeService and ensure that the right method gets loaded in tree.aspx
            if (activeTrees.Count == 1) {
                treeSvc.TreeType = activeTreeDefs[0].Tree.Alias;

                //convert the menu to a string
                string initActions = (TreeRequestParams.Instance.ShowContextMenu ? umbraco.BusinessLogic.Actions.Action.ToString(activeTrees[0].RootNodeActions) : "");

                //Since there's only 1 tree, render out the tree's RootNode properties
                PlaceHolderTree.Controls.Add(
                    new LiteralControl(
                        GetWebFxLoadTreeMethod(
                            activeTrees[0].RootNode.Text,
                            activeTrees[0].GetTreeServiceUrl(),
                            activeTrees[0].RootNode.Action,
                            activeTrees[0].RootNode.Icon,
                            activeTrees[0].RootNode.OpenIcon,
                            activeTrees[0].RootNode.NodeType,
                            activeTrees[0].StartNodeID.ToString(),
                            initActions)));
            } else {
                //If there is more than 1 tree for the application than render out a 
                //container node labelled with the current application.
                //TODO: Perhaps this node can be created in an IApplication since it will be application specific?
                PlaceHolderTree.Controls.Add(
                    new LiteralControl(
                        GetWebFxLoadTreeMethod(
                            ui.Text("sections", treeSvc.App, base.getUser()),
                            treeSvc.GetServiceUrl(),
                            "javascript:parent.openDashboard('" + treeSvc.App + @"');",
                            "",
                            "",
                            treeSvc.App.ToLower(),
                            "-1",
                            "")));
            }
        }

        /// <summary>
        /// Return the current application alias. If neither the TreeType of Application is specified
        /// than return the default application. If the Application is null but there is a TreeType then
        /// find the application that the tree type is associated with.
        /// </summary>
        /// <returns></returns>
        private string GetCurrApp() {
            //if theres an treetype specified but no application
            if (string.IsNullOrEmpty(TreeRequestParams.Instance.Application) &&
                !string.IsNullOrEmpty(TreeRequestParams.Instance.TreeType)) {
                TreeDefinition treeDef = TreeDefinitionCollection.Instance.FindTree(TreeRequestParams.Instance.TreeType);
                if (treeDef != null) return treeDef.App.alias;
            } else if (!string.IsNullOrEmpty(TreeRequestParams.Instance.Application))
                return TreeRequestParams.Instance.Application;

            //if everything is null then return the default app
            return DEFAULT_APP;
        }

        private void RenderTreeJS(List<BaseTree> trees) {
            StringBuilder javascript = new StringBuilder();
            foreach (BaseTree bTree in trees) {
                if (bTree.TreeAlias != "nodeTypes") {
                    bTree.RenderJS(ref javascript);
                } else {
                    javascript.Append(
                    @"
function openNodeType(id) {
	if (parent.opener)
		parent.opener.dialogHandler(id);
	else
		parent.dialogHandler(id);	
}

");
                }    
            }
            PlaceHolderJavascript.Controls.Add(new LiteralControl(javascript.ToString()));
        }

        /// <summary>
        /// Returns a formatted JavaScript block as a string for loading the tree using the WebFxTree library
        /// </summary>
        /// <param name="sText"></param>
        /// <param name="sXmlSrc"></param>
        /// <param name="xXmlSrcRoot"></param>
        /// <param name="sAction"></param>
        /// <param name="sBehavior"></param>
        /// <param name="sIcon"></param>
        /// <param name="sOpenIcon"></param>
        /// <param name="sNodeType"></param>
        /// <param name="sNodeID"></param>
        /// <param name="sMenu"></param>
        /// <returns></returns>
        private string GetWebFxLoadTreeMethod(string sText, string sXmlSrc, string sAction, string sIcon, string sOpenIcon, string sNodeType, string sNodeID, string sMenu) {
            string js = @"var tree = new WebFXLoadTree(""{0}"",""{1}"",""{2}"",""{3}"",""{4}"",""{5}"",""{6}"",""{7}"",""{8}"",""{9}"");document.writeln(tree);";
            string[] replacements = new string[] { sText, sXmlSrc, "", sAction, "", sIcon, sOpenIcon, sNodeType, sNodeID, sMenu };
            return String.Format(@"<script type=""text/javascript"">{0}</script>", String.Format(js, replacements));
        }
    }
}